The Java Virtual Machine Specification
نویسندگان
چکیده
methods and native methods are considered to be type safe if they do not override a final method. methodIsTypeSafe(Class, Method) :doesNotOverrideFinalMethod(Class, Method), methodAccessFlags(Method, AccessFlags), member(abstract, AccessFlags). methodIsTypeSafe(Class, Method) :doesNotOverrideFinalMethod(Class, Method), methodAccessFlags(Method, AccessFlags), member(native, AccessFlags). doesNotOverrideFinalMethod(class('java/lang/Object', L), Method) :isBootstrapLoader(L). doesNotOverrideFinalMethod(Class, Method) :classSuperClassName(Class, SuperclassName), classDefiningLoader(Class, L), loadedClass(SuperclassName, L, Superclass), classMethods(Superclass, MethodList), finalMethodNotOverridden(Method, Superclass, MethodList). finalMethodNotOverridden(Method, Superclass, MethodList) :methodName(Method, Name), methodDescriptor(Method, Descriptor), member(method(_, Name, Descriptor), MethodList), isNotFinal(Method, Superclass). finalMethodNotOverridden(Method, Superclass, MethodList) :methodName(Method, Name), methodDescriptor(Method, Descriptor), notMember(method(_, Name, Descriptor), MethodList), doesNotOverrideFinalMethod(Superclass, Method). THE CLASS FILE FORMAT Verification of class Files 4.10 167 4.10.1.6 Type Checking Methods with Code Non-abstract, non-native methods are type correct if they have code and the code is type correct. methodIsTypeSafe(Class, Method) :doesNotOverrideFinalMethod(Class, Method), methodAccessFlags(Method, AccessFlags), methodAttributes(Method, Attributes), notMember(native, AccessFlags), notMember(abstract, AccessFlags), member(attribute('Code', _), Attributes), methodWithCodeIsTypeSafe(Class, Method). A method with code is type safe if it is possible to merge the code and the stack map frames into a single stream such that each stack map frame precedes the instruction it corresponds to, and the merged stream is type correct. The method's exception handlers, if any, must also be legal. methodWithCodeIsTypeSafe(Class, Method) :parseCodeAttribute(Class, Method, FrameSize, MaxStack, ParsedCode, Handlers, StackMap), mergeStackMapAndCode(StackMap, ParsedCode, MergedCode), methodInitialStackFrame(Class, Method, FrameSize, StackFrame, ReturnType), Environment = environment(Class, Method, ReturnType, MergedCode, MaxStack, Handlers), handlersAreLegal(Environment), mergedCodeIsTypeSafe(Environment, MergedCode, StackFrame). 4.10 Verification of class Files THE CLASS FILE FORMAT 168 Let us consider exception handlers first. An exception handler is represented by a functor application of the form: handler(Start, End, Target, ClassName) whose arguments are, respectively, the start and end of the range of instructions covered by the handler, the first instruction of the handler code, and the name of the exception class that this handler is designed to handle. An exception handler is legal if its start (Start) is less than its end (End), there exists an instruction whose offset is equal to Start, there exists an instruction whose offset equals End, and the handler's exception class is assignable to the class Throwable. The exception class of a handler is Throwable if the handler's class entry is 0, otherwise it is the class named in the handler. handlersAreLegal(Environment) :exceptionHandlers(Environment, Handlers), checklist(handlerIsLegal(Environment), Handlers). handlerIsLegal(Environment, Handler) :Handler = handler(Start, End, Target, _), Start < End, allInstructions(Environment, Instructions), member(instruction(Start, _), Instructions), offsetStackFrame(Environment, Target, _), instructionsIncludeEnd(Instructions, End), currentClassLoader(Environment, CurrentLoader), handlerExceptionClass(Handler, ExceptionClass, CurrentLoader), isBootstrapLoader(BL), isAssignable(ExceptionClass, class('java/lang/Throwable', BL)). instructionsIncludeEnd(Instructions, End) :member(instruction(End, _), Instructions). instructionsIncludeEnd(Instructions, End) :member(endOfCode(End), Instructions). handlerExceptionClass(handler(_, _, _, 0), class('java/lang/Throwable', BL), _) :isBootstrapLoader(BL). handlerExceptionClass(handler(_, _, _, Name), class(Name, L), L) :Name \= 0. THE CLASS FILE FORMAT Verification of class Files 4.10 169 Let us now turn to the stream of instructions and stack map frames. Merging instructions and stack map frames into a single stream involves four cases: • Merging an empty StackMap and a list of instructions yields the original list of instructions. mergeStackMapAndCode([], CodeList, CodeList). • Given a list of stack map frames beginning with the type state for the instruction at Offset, and a list of instructions beginning at Offset, the merged list is the head of the stack frame list, followed by the head of the instruction list, followed by the merge of the tails of the two lists. mergeStackMapAndCode([stackMap(Offset, Map) | RestMap], [instruction(Offset, Parse) | RestCode], [stackMap(Offset, Map), instruction(Offset, Parse) | RestMerge]) :mergeStackMapAndCode(RestMap, RestCode, RestMerge). • Otherwise, given a list of stack frames beginning with the type state for the instruction at OffsetM, and a list of instructions beginning at OffsetP, then, if OffsetP < OffsetM, the merged list consists of the head of the instruction list, followed by the merge of the stack frame list and the tail of the instruction list. mergeStackMapAndCode([stackMap(OffsetM, Map) | RestMap], [instruction(OffsetP, Parse) | RestCode], [instruction(OffsetP, Parse) | RestMerge]) :OffsetP < OffsetM, mergeStackMapAndCode([stackMap(OffsetM, Map) | RestMap], RestCode, RestMerge). • Otherwise, the merge of the two lists is undefined. Since the instruction list has monotonically increasing offsets, the merge of the two lists is not defined unless every stack map frame offset has a corresponding instruction offset and the stack map frames are in monotonically increasing order. 4.10 Verification of class Files THE CLASS FILE FORMAT 170 To determine if the merged stream for a method is type correct, we first infer the method's initial type state. The initial type state of a method consists of an empty operand stack and local variable types derived from the type of this and the arguments, as well as the appropriate flag, depending on whether this is an method. methodInitialStackFrame(Class, Method, FrameSize, frame(Locals, [], Flags), ReturnType):methodDescriptor(Method, Descriptor), parseMethodDescriptor(Descriptor, RawArgs, ReturnType), expandTypeList(RawArgs, Args), methodInitialThisType(Class, Method, ThisList), flags(ThisList, Flags), append(ThisList, Args, ThisArgs), expandToLength(ThisArgs, FrameSize, top, Locals). Given a list of types, the following clause produces a list where every type of size 2 has been substituted by two entries: one for itself, and one top entry. The result then corresponds to the representation of the list as 32-bit words in the Java Virtual Machine. expandTypeList([], []). expandTypeList([Item | List], [Item | Result]) :sizeOf(Item, 1), expandTypeList(List, Result). expandTypeList([Item | List], [Item, top | Result]) :sizeOf(Item, 2), expandTypeList(List, Result). flags([uninitializedThis], [flagThisUninit]). flags(X, []) :X \= [uninitializedThis]. expandToLength(List, Size, _Filler, List) :length(List, Size). expandToLength(List, Size, Filler, Result) :length(List, ListLength), ListLength < Size, Delta is Size ListLength, length(Extra, Delta), checklist(=(Filler), Extra), append(List, Extra, Result). THE CLASS FILE FORMAT Verification of class Files 4.10 171 For the initial type state of an instance method, we compute the type of this and put it in a list. The type of this in the method of Object is Object; in other methods, the type of this is uninitializedThis; otherwise, the type of this in an instance method is class(N, L) where N is the name of the class containing the method and L is its defining class loader. For the initial type state of a static method, this is irrelevant, so the list is empty. methodInitialThisType(_Class, Method, []) :methodAccessFlags(Method, AccessFlags), member(static, AccessFlags), methodName(Method, MethodName), MethodName \= ''. methodInitialThisType(Class, Method, [This]) :methodAccessFlags(Method, AccessFlags),\ notMember(static, AccessFlags),\ instanceMethodInitialThisType(Class, Method, This). instanceMethodInitialThisType(Class, Method, class('java/lang/Object', L)) :methodName(Method, ''), classDefiningLoader(Class, L), isBootstrapLoader(L), classClassName(Class, 'java/lang/Object'). instanceMethodInitialThisType(Class, Method, uninitializedThis) :methodName(Method, ''), classClassName(Class, ClassName), classDefiningLoader(Class, CurrentLoader), superclassChain(ClassName, CurrentLoader, Chain), Chain \= []. instanceMethodInitialThisType(Class, Method, class(ClassName, L)) :methodName(Method, MethodName), MethodName \= '', classDefiningLoader(Class, L), classClassName(Class, ClassName). 4.10 Verification of class Files THE CLASS FILE FORMAT 172 We now compute whether the merged stream for a method is type correct, using the method's initial type state: • If we have a stack map frame and an incoming type state, the type state must be assignable to the one in the stack map. We may then proceed to type check the rest of the stream with the type state given in the stack map. mergedCodeIsTypeSafe(Environment, [stackMap(Offset, MapFrame) | MoreCode], frame(Locals, OperandStack, Flags)) :frameIsAssignable(frame(Locals, OperandStack, Flags), MapFrame), mergedCodeIsTypeSafe(Environment, MoreCode, MapFrame). • A merged code stream is type safe relative to an incoming type state T if it begins with an instruction I that is type safe relative to T, and I satisfies its exception handlers (see below), and the tail of the stream is type safe given the type state following that execution of I. NextStackFrame indicates what falls through to the following instruction. For an unconditional branch instruction, it will have the special value afterGoto. ExceptionStackFrame indicates what is passed to exception handlers. mergedCodeIsTypeSafe(Environment, [instruction(Offset, Parse) | MoreCode], frame(Locals, OperandStack, Flags)) :instructionIsTypeSafe(Parse, Environment, Offset, frame(Locals, OperandStack, Flags), NextStackFrame, ExceptionStackFrame), instructionSatisfiesHandlers(Environment, Offset, ExceptionStackFrame), mergedCodeIsTypeSafe(Environment, MoreCode, NextStackFrame). • After an unconditional branch (indicated by an incoming type state of afterGoto), if we have a stack map giving the type state for the following instructions, we can proceed and type check them using the type state provided by the stack map. mergedCodeIsTypeSafe(Environment, [stackMap(Offset, MapFrame) | MoreCode], afterGoto) :mergedCodeIsTypeSafe(Environment, MoreCode, MapFrame). • It is illegal to have code after an unconditional branch without a stack map frame being provided for it. mergedCodeIsTypeSafe(_Environment, [instruction(_, _) | _MoreCode], afterGoto) :write_ln('No stack frame after unconditional branch'), fail. • If we have an unconditional branch at the end of the code, stop. THE CLASS FILE FORMAT Verification of class Files 4.10 173 mergedCodeIsTypeSafe(_Environment, [endOfCode(Offset)], afterGoto). Branching to a target is type safe if the target has an associated stack frame, Frame, and the current stack frame, StackFrame, is assignable to Frame. targetIsTypeSafe(Environment, StackFrame, Target) :offsetStackFrame(Environment, Target, Frame), frameIsAssignable(StackFrame, Frame). An instruction satisfies its exception handlers if it satisfies every exception handler that is applicable to the instruction. instructionSatisfiesHandlers(Environment, Offset, ExceptionStackFrame) :exceptionHandlers(Environment, Handlers), sublist(isApplicableHandler(Offset), Handlers, ApplicableHandlers), checklist(instructionSatisfiesHandler(Environment, ExceptionStackFrame), ApplicableHandlers). An exception handler is applicable to an instruction if the offset of the instruction is greater or equal to the start of the handler's range and less than the end of the handler's range. isApplicableHandler(Offset, handler(Start, End, _Target, _ClassName)) :Offset >= Start, Offset < End. An instruction satisfies an exception handler if its incoming type state is StackFrame, and the handler's target (the initial instruction of the handler code) is type safe assuming an incoming type state T. The type state T is derived from StackFrame by replacing the operand stack with a stack whose sole element is the handler's exception class. instructionSatisfiesHandler(Environment, StackFrame, Handler) :Handler = handler(_, _, Target, _), currentClassLoader(Environment, CurrentLoader), handlerExceptionClass(Handler, ExceptionClass, CurrentLoader), /* The stack consists of just the exception. */ StackFrame = frame(Locals, _, Flags), ExcStackFrame = frame(Locals, [ ExceptionClass ], Flags), operandStackHasLegalLength(Environment, ExcStackFrame), targetIsTypeSafe(Environment, ExcStackFrame, Target). 4.10 Verification of class Files THE CLASS FILE FORMAT 174 4.10.1.7 Type Checking Load and Store Instructions All load instructions are variations on a common pattern, varying the type of the value that the instruction loads. Loading a value of type Type from local variable Index is type safe, if the type of that local variable is ActualType, ActualType is assignable to Type, and pushing ActualType onto the incoming operand stack is a valid type transition (§4.10.1.4) that yields a new type state NextStackFrame. After execution of the load instruction, the type state will be NextStackFrame. loadIsTypeSafe(Environment, Index, Type, StackFrame, NextStackFrame) :StackFrame = frame(Locals, _OperandStack, _Flags), nth0(Index, Locals, ActualType), isAssignable(ActualType, Type), validTypeTransition(Environment, [], ActualType, StackFrame, NextStackFrame). All store instructions are variations on a common pattern, varying the type of the value that the instruction stores. In general, a store instruction is type safe if the local variable it references is of a type that is a supertype of Type, and the top of the operand stack is of a subtype of Type, where Type is the type the instruction is designed to store. More precisely, the store is type safe if one can pop a type ActualType that "matches" Type (that is, is a subtype of Type) off the operand stack (§4.10.1.4), and then legally assign that type the local variable LIndex. storeIsTypeSafe(_Environment, Index, Type, frame(Locals, OperandStack, Flags), frame(NextLocals, NextOperandStack, Flags)) :popMatchingType(OperandStack, Type, NextOperandStack, ActualType), modifyLocalVariable(Index, ActualType, Locals, NextLocals). Given local variables Locals, modifying Index to have type Type results in the local variable list NewLocals. The modifications are somewhat involved, because some values (and their corresponding types) occupy two local variables. Hence, modifying LN may require modifying LN+1 (because the type will occupy both the N and N+1 slots) or LN-1 (because local N used to be the upper half of the two word value/type starting at local N-1, and so local N-1 must be invalidated), or both. This is described further below. We start at L0 and count up. modifyLocalVariable(Index, Type, Locals, NewLocals) :modifyLocalVariable(0, Index, Type, Locals, NewLocals). THE CLASS FILE FORMAT Verification of class Files 4.10 175 Given LocalsRest, the suffix of the local variable list starting at index I, modifying local variable Index to have type Type results in the local variable list suffix NextLocalsRest. If I < Index-1, just copy the input to the output and recurse forward. If I = Index-1, the type of local I may change. This can occur if LI has a type of size 2. Once we set LI+1 to the new type (and the corresponding value), the type/value of LI will be invalidated, as its upper half will be trashed. Then we recurse forward. modifyLocalVariable(I, Index, Type, [Locals1 | LocalsRest], [Locals1 | NextLocalsRest] ) :I < Index 1, I1 is I + 1, modifyLocalVariable(I1, Index, Type, LocalsRest, NextLocalsRest). modifyLocalVariable(I, Index, Type, [Locals1 | LocalsRest], [NextLocals1 | NextLocalsRest] ) :I =:= Index 1, modifyPreIndexVariable(Locals1, NextLocals1), modifyLocalVariable(Index, Index, Type, LocalsRest, NextLocalsRest). When we find the variable, and it only occupies one word, we change it to Type and we're done. When we find the variable, and it occupies two words, we change its type to Type and the next word to top. modifyLocalVariable(Index, Index, Type, [_ | LocalsRest], [Type | LocalsRest]) :sizeOf(Type, 1). modifyLocalVariable(Index, Index, Type, [_, _ | LocalsRest], [Type, top | LocalsRest]) :sizeOf(Type, 2). We refer to a local whose index immediately precedes a local whose type will be modified as a pre-index variable. The future type of a pre-index variable of type InputType is Result. If the type, Type, of the pre-index local is of size 1, it doesn't change. If the type of the pre-index local, Type, is 2, we need to mark the lower half of its two word value as unusable, by setting its type to top. modifyPreIndexVariable(Type, Type) :sizeOf(Type, 1). modifyPreIndexVariable(Type, top) :sizeOf(Type, 2). 4.10 Verification of class Files THE CLASS FILE FORMAT 176 4.10.1.8 Type Checking for protected Members All instructions that access members must contend with the rules concerning protected members. This section describes the protected check that corresponds to JLS §6.6.2.1. The protected check applies only to protected members of superclasses of the current class. protected members in other classes will be caught by the access checking done at resolution (§5.4.4). There are four cases: • If the name of a class is not the name of any superclass, it cannot be a superclass, and so it can safely be ignored. passesProtectedCheck(Environment, MemberClassName, MemberName, MemberDescriptor, StackFrame) :thisClass(Environment, class(CurrentClassName, CurrentLoader)), superclassChain(CurrentClassName, CurrentLoader, Chain), notMember(class(MemberClassName, _), Chain). • If the MemberClassName is the same as the name of a superclass, the class being resolved may indeed be a superclass. In this case, if no superclass named MemberClassName in a different run-time package has a protected member named MemberName with descriptor MemberDescriptor, the protected check does not apply. This is because the actual class being resolved will either be one of these superclasses, in which case we know that it is either in the same run-time package, and the access is legal; or the member in question is not protected and the check does not apply; or it will be a subclass, in which case the check would succeed anyway; or it will be some other class in the same run-time package, in which case the access is legal and the check need not take place; or the verifier need not flag this as a problem, since it will be caught anyway because resolution will per force fail. passesProtectedCheck(Environment, MemberClassName, MemberName, MemberDescriptor, StackFrame) :thisClass(Environment, class(CurrentClassName, CurrentLoader)), superclassChain(CurrentClassName, CurrentLoader, Chain), member(class(MemberClassName, _), Chain), classesInOtherPkgWithProtectedMember( class(CurrentClassName, CurrentLoader), MemberName, MemberDescriptor, MemberClassName, Chain, []). • If there does exist a protected superclass member in a different run-time package, then load MemberClassName; if the member in question is not protected, the check does not apply. (Using a superclass member that is not protected is trivially correct.) THE CLASS FILE FORMAT Verification of class Files 4.10 177 passesProtectedCheck(Environment, MemberClassName, MemberName, MemberDescriptor, frame(_Locals, [Target | Rest], _Flags)) :thisClass(Environment, class(CurrentClassName, CurrentLoader)), superclassChain(CurrentClassName, CurrentLoader, Chain), member(class(MemberClassName, _), Chain), classesInOtherPkgWithProtectedMember( class(CurrentClassName, CurrentLoader), MemberName, MemberDescriptor, MemberClassName, Chain, List), List /= [], loadedClass(MemberClassName, CurrentLoader, ReferencedClass), isNotProtected(ReferencedClass, MemberName, MemberDescriptor). • Otherwise, use of a member of an object of type Target requires that Target be assignable to the type of the current class. passesProtectedCheck(Environment, MemberClassName, MemberName, MemberDescriptor, frame(_Locals, [Target | Rest], _Flags)) :thisClass(Environment, class(CurrentClassName, CurrentLoader)), superclassChain(CurrentClassName, CurrentLoader, Chain), member(class(MemberClassName, _), Chain), classesInOtherPkgWithProtectedMember( class(CurrentClassName, CurrentLoader), MemberName, MemberDescriptor, MemberClassName, Chain, List), List /= [], loadedClass(MemberClassName, CurrentLoader, ReferencedClass), isProtected(ReferencedClass, MemberName, MemberDescriptor), isAssignable(Target, class(CurrentClassName, CurrentLoader)). The predicate classesInOtherPkgWithProtectedMember(Class, MemberName, MemberDescriptor, MemberClassName, Chain, List) is true if List is the set of classes in Chain with name MemberClassName that are in a different run-time package than Class which have a protected member named MemberName with descriptor MemberDescriptor. 4.10 Verification of class Files THE CLASS FILE FORMAT 178 classesInOtherPkgWithProtectedMember(_, _, _, _, [], []). classesInOtherPkgWithProtectedMember(Class, MemberName, MemberDescriptor, MemberClassName, [class(MemberClassName, L) | Tail], [class(MemberClassName, L) | T]) :differentRuntimePackage(Class, class(MemberClassName, L)), loadedClass(MemberClassName, L, Super), isProtected(Super, MemberName, MemberDescriptor), classesInOtherPkgWithProtectedMember( Class, MemberName, MemberDescriptor, MemberClassName, Tail, T). classesInOtherPkgWithProtectedMember(Class, MemberName, MemberDescriptor, MemberClassName, [class(MemberClassName, L) | Tail], T) :differentRuntimePackage(Class, class(MemberClassName, L)), loadedClass(MemberClassName, L, Super), isNotProtected(Super, MemberName, MemberDescriptor), classesInOtherPkgWithProtectedMember( Class, MemberName, MemberDescriptor, MemberClassName, Tail, T). classesInOtherPkgWithProtectedMember(Class, MemberName, MemberDescriptor, MemberClassName, [class(MemberClassName, L) | Tail], T] :sameRuntimePackage(Class, class(MemberClassName, L)), classesInOtherPkgWithProtectedMember( Class, MemberName, MemberDescriptor, MemberClassName, Tail, T). sameRuntimePackage(Class1, Class2) :classDefiningLoader(Class1, L), classDefiningLoader(Class2, L), samePackageName(Class1, Class2). differentRuntimePackage(Class1, Class2) :classDefiningLoader(Class1, L1), classDefiningLoader(Class2, L2), L1 \= L2. differentRuntimePackage(Class1, Class2) :differentPackageName(Class1, Class2). THE CLASS FILE FORMAT Verification of class Files 4.10 179 4.10.1.9 Type Checking Instructions In general, the type rule for an instruction is given relative to an environment Environment that defines the class and method in which the instruction occurs (§4.10.1.1), and the offset Offset within the method at which the instruction occurs. The rule states that if the incoming type state StackFrame fulfills certain requirements, then: • The instruction is type safe. • It is provable that the type state after the instruction completes normally has a particular form given by NextStackFrame, and that the type state after the instruction completes abruptly is given by ExceptionStackFrame. The type state after an instruction completes abruptly is the same as the incoming type state, except that the operand stack is empty. exceptionStackFrame(StackFrame, ExceptionStackFrame) :StackFrame = frame(Locals, _OperandStack, Flags), ExceptionStackFrame = frame(Locals, [], Flags). Many instructions have type rules that are completely isomorphic to the rules for other instructions. If an instruction b1 is isomorphic to another instruction b2, then the type rule for b1 is the same as the type rule for b2. instructionIsTypeSafe(Instruction, Environment, Offset, StackFrame, NextStackFrame, ExceptionStackFrame) :instructionHasEquivalentTypeRule(Instruction, IsomorphicInstruction), instructionIsTypeSafe(IsomorphicInstruction, Environment, Offset, StackFrame, NextStackFrame, ExceptionStackFrame). The English language description of each rule is intended to be readable, intuitive, and concise. As such, the description avoids repeating all the contextual assumptions given above. In particular: • The description does not explicitly mention the environment. • When the description speaks of the operand stack or local variables in the following, it is referring to the operand stack and local variable components of a type state: either the incoming type state or the outgoing one. • The type state after the instruction completes abruptly is almost always identical to the incoming type state. The description only discusses the type state after the instruction completes abruptly when that is not the case. 4.10 Verification of class Files THE CLASS FILE FORMAT 180 • The description speaks of popping and pushing types onto the operand stack, and does not explicitly discuss issues of stack underflow or overflow. The description assumes these operations can be completed successfully, but the Prolog clauses for operand stack manipulation ensure that the necessary checks are made. • The description discusses only the manipulation of logical types. In practice, some types take more than one word. The description abstracts from these representation details, but the Prolog clauses that manipulate data do not. Any ambiguities can be resolved by referring to the formal Prolog clauses. THE CLASS FILE FORMAT Verification of class Files 4.10
منابع مشابه
Proposal for Extension of JavaTM Floating Point
Prompted by feedback from several partners in the industry, Sun is proposing a change to the specification of floating-point in the Java programming language. The current Java programming language and virtual machine specifications require that all single and double precision floating-point calculations must round their results to the IEEE 754 single and double precision formats, respectively. ...
متن کاملImproving the official specification of Java bytecode verification
Bytecode verification is the main mechanism to ensure type safety in the Java Virtual Machine. Inadequacies in its official specification may lead to incorrect implementations where security can be broken and/or certain legal programs are rejected. This paper provides a comprehensive analysis of the specification, along with concrete suggestions for improvement. Copyright c © 2003 John Wiley & ...
متن کاملGeneration of Efficient Virtual Machine ( Extended Abstract )
TokyoTech Virtual Machine Builder (VMB) is a generator of virtual machines. VMB takes a formal specification of a virtual machine and generates implementation of the virtual machine. A specification of a virtual machine comprises configuration of virtual hardware (a set of virtual registers, virtual stacks, and heap organization) and definition of virtual machine instruction set. Behavior of ea...
متن کاملCoqJVM: An Executable Specification of the Java Virtual Machine Using Dependent Types
We describe an executable specification of the Java Virtual Machine (JVM) within the Coq proof assistant. The principal features of the development are that it is executable, meaning that it can be tested against a real JVM to gain confidence in the correctness of the specification; and that it has been written with heavy use of dependent types, this is both to structure the model in a useful w...
متن کاملA Type System for Object Initialization In the JavaTM Bytecode Language
In the standard Java implementation, a Java language program is compiled to Java bytecode and this bytecode is then interpreted by the Java Virtual Machine. Since bytecode may be written by hand, or corrupted during network transmission, the Java Virtual Machine contains a bytecode verifier that performs a number of consistency checks before code is interpreted. However, there is no formal spec...
متن کاملTowards an Algebraic Specification of the Java Virtual Machine
We develop an algebraic speci cation of the architecture of an abstract and simpli ed version of the Java Virtual Machine (JVM). This concentration on the implementation-independent features of the machine allows us to build a clean and easily comprehensible model in which its structure is emphasised. We then axiomatise the semantics of programs operating on this architecture. We also consider ...
متن کامل